﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace Q42.Wheels.Mvc.Paging
{
  [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
  public class PagingAttribute : ActionFilterAttribute
  {
    public string PagingName { get; set; }

    public int PageSize { get; set; }

    public string PaginationUserControlName { get; set; }

    public string DefaultSortColumn { get; set; }

    public bool KeepPageAfterSort { get; set; }

    public string[] VaryByParams { get; set; }

    public PagingAttribute()
      : this(Paging.DefaultPagingName, Paging.DefaultPageSize)
    {      
    }

    public PagingAttribute(string pagingName)
      : this(pagingName, Paging.DefaultPageSize)
    {
      PagingName = pagingName;
    }

    public PagingAttribute(string paginationName, int pageSize)
    {
      PagingName = paginationName;
      PageSize = pageSize;
      VaryByParams = new string[] { };
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
      if (!filterContext.Controller.ViewData.ContainsKey(PagingName))
      {
        filterContext.Controller.ViewData[PagingName] = new Paging(PagingName);
      }

      Paging paging = filterContext.Controller.ViewData[PagingName] as Paging;
      paging.NumberPerPage = PageSize;

      if (!String.IsNullOrEmpty(PaginationUserControlName))
        paging.PaginationUserControlName = PaginationUserControlName;

      paging.KeepPageAfterSort = KeepPageAfterSort;

      if (filterContext.Controller.ValueProvider.ContainsPrefix(paging.PageParameterName))
      {
        paging.CurrentPage = Convert.ToInt32(filterContext.Controller.ValueProvider.GetValue(paging.PageParameterName).AttemptedValue);
      }
      else
      {
        paging.CurrentPage = 0;
      }

      foreach (string param in VaryByParams)
      {
        if(filterContext.Controller.ValueProvider.ContainsPrefix(param))
        {
          if (paging.VaryByParamsValues == null)
            paging.VaryByParamsValues = new Dictionary<string, string>();

          paging.VaryByParamsValues[param] = filterContext.Controller.ValueProvider.GetValue(param).AttemptedValue;

          if(filterContext.Controller.ValueProvider.ContainsPrefix(String.Format("{0}.{1}", paging.PagingName, param)))
          {
            if (filterContext.Controller.ValueProvider.GetValue(param).AttemptedValue != filterContext.Controller.ValueProvider.GetValue(String.Format("{0}.{1}", paging.PagingName, param)).AttemptedValue)
              paging.CurrentPage = 0;
          }
          else
          {
            paging.CurrentPage = 0;
          }
        }
      }

      if (filterContext.Controller.ValueProvider.ContainsPrefix(paging.SortParameterName))
      {
        paging.Sort = filterContext.Controller.ValueProvider.GetValue(paging.SortParameterName).AttemptedValue;
      }
      else if(!String.IsNullOrWhiteSpace(DefaultSortColumn))
      {
        paging.Sort = DefaultSortColumn;
      }

      if (filterContext.Controller.ValueProvider.ContainsPrefix(paging.SortDescendingParameterName))
      {
        paging.SortDescending = true;
      }
    }
  }
}
